#ifndef MIX_log2_M_H
#define MIX_log2_M_H

#include "stdint.h"
#include "rtctime.h"
#include "mytype.h"

#ifdef __cplusplus
extern "C"
{
#endif

#define MIX_FLAG_ST_0 15
#define MIX_FLAG_ST_1 7
#define MIX_FLAG_ST_2 3
#define MIX_FLAG_ST_3 1
#define MIX_FLAG_ST_4 0

	struct mix_log_head_str
	{
		uint32_t tim;	   
		uint16_t addr;	   
		uint16_t len : 12; 
		uint16_t flag : 4; 
	};

	typedef struct mix_log_head_str mix_log_head_type;

	struct mix_log_info_str
	{
		uint32_t page_amount;
		uint32_t page_now;
		uint32_t page_start;
		uint16_t site_next;
		uint16_t dat_addr_last;
	};

	typedef struct mix_log_info_str mix_log_info_type;

	struct mix_log_obj_str
	{
		uint32_t page_site;
		uint16_t sub_site;
		mix_log_head_type log_head;
		uint8_t *dat;
	};

	typedef struct mix_log_obj_str mix_log_obj_type;

	struct mix_log_api_str
	{
		void (*init)(void);
		void (*save)(uint32_t tim, void *dat, uint16_t len);
		void (*read)(mix_log_obj_type *log_obj);
		void (*clr)(void);
		void (*flag_set)(mix_log_obj_type *log_obj, uu08 flag);
		int (*site_move)(mix_log_obj_type *log_obj, int movesite);
		ii08 (*is_site_valid)(mix_log_obj_type *log_site);
		void (*modify)(mix_log_obj_type *log_site, ii16 offset, void *dat, ii16 len);

		int (*blk_iter)(
			uint32_t page_start, uint32_t blk_end, uu16 flag,
			ii08 (*iter_back)(mix_log_obj_type *obj), mix_log_obj_type *log_obj);

		int (*site_iter)(
			mix_log_obj_type *s_start, mix_log_obj_type *s_end, uu16 flag,
			ii08 (*iter_back)(mix_log_obj_type *obj), mix_log_obj_type *log_obj);

		int (*time_iter)(
			uint32_t tim_start, uint32_t tim_end, uu16 flag,
			ii08 (*iter_back)(mix_log_obj_type *obj), mix_log_obj_type *log_obj);

		int (*m_site_iter)(
			mix_log_obj_type *s_start, mix_log_obj_type *s_end, uu16 flag,
			ii08 (*iter_back)(mix_log_obj_type *obj));

		int (*m_time_iter)(
			uint32_t tim_start, uint32_t tim_end, uu16 flag,
			ii08 (*iter_back)(mix_log_obj_type *obj));

		int32_t (*time_search)(uint32_t time, int8_t mode, mix_log_obj_type *obj);
	};

	typedef struct mix_log_api_str mix_log_api_type;

	struct mix_log_str
	{
		uint32_t addr_base;											
		uint32_t total_size;										
		uint16_t page_size;											
		uint16_t log_size_max;										
		mix_log_info_type *info;									
		void (*Erase)(uint32_t AddrBase);							
		void (*Program)(uint32_t Addr, uint8_t *dat, uint16_t Len); 
		void (*Read)(uint32_t Addr, uint8_t *dat, uint16_t Len);	
		const mix_log_api_type *api;
	};

	typedef struct mix_log_str mix_log_type;

	void mix_log_init(const mix_log_type *cfg);

	void mix_log_save(const mix_log_type *cfg, uint32_t tim, void *dat, uint16_t len); 

	void mix_log_read(const mix_log_type *cfg, mix_log_obj_type *log_obj);

	void mix_log_clr(const mix_log_type *cfg);

	void mix_log_flag_set(const mix_log_type *cfg, mix_log_obj_type *log_obj, uu08 flag); 

	int mix_log_site_move(const mix_log_type *cfg, mix_log_obj_type *log_obj, int movesite);

	void mix_log_modify(const mix_log_type *cfg, mix_log_obj_type *log_site, ii16 offset, void *dat, ii16 len);

	ii08 mix_log_is_site_valid(const mix_log_type *cfg, mix_log_obj_type *log_site);

	int mix_log_blk_iter(
		const mix_log_type *cfg, uint32_t page_start, uint32_t blk_end, uu16 flag,
		ii08 (*iter_back)(mix_log_obj_type *obj), mix_log_obj_type *log_obj);

	int mix_log_site_iter(
		const mix_log_type *cfg, mix_log_obj_type *s_start, mix_log_obj_type *s_end, uu16 flag,
		ii08 (*iter_back)(mix_log_obj_type *obj), mix_log_obj_type *log_obj);

	int mix_log_time_iter(
		const mix_log_type *cfg, uint32_t tim_start, uint32_t tim_end, uu16 flag,
		ii08 (*iter_back)(mix_log_obj_type *obj), mix_log_obj_type *log_obj);

	int mix_log_m_site_iter(
		const mix_log_type *cfg, mix_log_obj_type *s_start, mix_log_obj_type *s_end, uu16 flag,
		ii08 (*iter_back)(mix_log_obj_type *obj));

	int mix_log_m_time_iter(
		const mix_log_type *cfg, uint32_t tim_start, uint32_t tim_end, uu16 flag,
		ii08 (*iter_back)(mix_log_obj_type *obj));

	int32_t mix_log_time_search(const mix_log_type *cfg, uint32_t time, int8_t mode, mix_log_obj_type *obj);

#define mix_log_api_make(obj)                                                               \
                                                                                            \
	static void obj##_init(void);                                                           \
	static void obj##_save(uint32_t tim, void *dat, uint16_t len);                          \
	static void obj##_read(mix_log_obj_type *log_obj);                                      \
	static void obj##_clr(void);                                                            \
	static void obj##_flag_set(mix_log_obj_type *log_obj, uu08 flag);                       \
	static int obj##_site_move(mix_log_obj_type *log_obj, int movesite);                    \
	static ii08 obj##_is_site_valid(mix_log_obj_type *log_site);                            \
	static void obj##_modify(mix_log_obj_type *log_site, ii16 offset, void *dat, ii16 len); \
	static int32_t obj##_time_search(uint32_t time, int8_t mode, mix_log_obj_type *logobj); \
	static int obj##_blk_iter(                                                              \
		uint32_t page_start, uint32_t blk_end, uu16 flag,                                   \
		ii08 (*iter_back)(mix_log_obj_type * obj), mix_log_obj_type *log_obj);              \
	static int obj##_site_iter(                                                             \
		mix_log_obj_type *s_start, mix_log_obj_type *s_end, uu16 flag,                      \
		ii08 (*iter_back)(mix_log_obj_type * obj), mix_log_obj_type *log_obj);              \
	static int obj##_time_iter(                                                             \
		uint32_t tim_start, uint32_t tim_end, uu16 flag,                                    \
		ii08 (*iter_back)(mix_log_obj_type * obj), mix_log_obj_type *log_obj);              \
	static int obj##_m_site_iter(                                                           \
		mix_log_obj_type *s_start, mix_log_obj_type *s_end, uu16 flag,                      \
		ii08 (*iter_back)(mix_log_obj_type * obj));                                         \
	static int obj##_m_time_iter(                                                           \
		uint32_t tim_start, uint32_t tim_end, uu16 flag,                                    \
		ii08 (*iter_back)(mix_log_obj_type * obj));                                         \
                                                                                            \
	static void obj##_init(void)                                                            \
	{                                                                                       \
		mix_log_init(&obj);                                                                 \
	}                                                                                       \
	static void obj##_save(uint32_t tim, void *dat, uint16_t len)                           \
	{                                                                                       \
		mix_log_save(&obj, tim, dat, len);                                                  \
	}                                                                                       \
	static void obj##_read(mix_log_obj_type *log_obj)                                       \
	{                                                                                       \
		mix_log_read(&obj, log_obj);                                                        \
	}                                                                                       \
	void obj##_clr(void)                                                                    \
	{                                                                                       \
		mix_log_clr(&obj);                                                                  \
	}                                                                                       \
	static void obj##_flag_set(mix_log_obj_type *log_obj, uu08 flag)                        \
	{                                                                                       \
		mix_log_flag_set(&obj, log_obj, flag);                                              \
	}                                                                                       \
	static int obj##_site_move(mix_log_obj_type *log_obj, int movesite)                     \
	{                                                                                       \
		return mix_log_site_move(&obj, log_obj, movesite);                                  \
	}                                                                                       \
	static ii08 obj##_is_site_valid(mix_log_obj_type *log_site)                             \
	{                                                                                       \
		return mix_log_is_site_valid(&obj, log_site);                                       \
	}                                                                                       \
	static void obj##_modify(mix_log_obj_type *log_site, ii16 offset, void *dat, ii16 len)  \
	{                                                                                       \
		mix_log_modify(&obj, log_site, offset, dat, len);                                   \
	}                                                                                       \
	static int32_t obj##_time_search(uint32_t time, int8_t mode, mix_log_obj_type *logobj)  \
	{                                                                                       \
		return mix_log_time_search(&obj, time, mode, logobj);                               \
	}                                                                                       \
	static int obj##_blk_iter(                                                              \
		uint32_t page_start, uint32_t blk_end, uu16 flag,                                   \
		ii08 (*iter_back)(mix_log_obj_type * obj), mix_log_obj_type *log_obj)               \
	{                                                                                       \
		return mix_log_blk_iter(&obj, page_start, blk_end, flag, iter_back, log_obj);       \
	}                                                                                       \
	static int obj##_site_iter(                                                             \
		mix_log_obj_type *s_start, mix_log_obj_type *s_end, uu16 flag,                      \
		ii08 (*iter_back)(mix_log_obj_type * obj), mix_log_obj_type *log_obj)               \
	{                                                                                       \
		return mix_log_site_iter(&obj, s_start, s_end, flag, iter_back, log_obj);           \
	}                                                                                       \
	static int obj##_time_iter(                                                             \
		uint32_t tim_start, uint32_t tim_end, uu16 flag,                                    \
		ii08 (*iter_back)(mix_log_obj_type * obj), mix_log_obj_type *log_obj)               \
	{                                                                                       \
		return mix_log_time_iter(&obj, tim_start, tim_end, flag, iter_back, log_obj);       \
	}                                                                                       \
	static int obj##_m_site_iter(                                                           \
		mix_log_obj_type *s_start, mix_log_obj_type *s_end, uu16 flag,                      \
		ii08 (*iter_back)(mix_log_obj_type * obj))                                          \
	{                                                                                       \
		return mix_log_m_site_iter(&obj, s_start, s_end, flag, iter_back);                  \
	}                                                                                       \
	static int obj##_m_time_iter(                                                           \
		uint32_t tim_start, uint32_t tim_end, uu16 flag,                                    \
		ii08 (*iter_back)(mix_log_obj_type * obj))                                          \
	{                                                                                       \
		return mix_log_m_time_iter(&obj, tim_start, tim_end, flag, iter_back);              \
	}                                                                                       \
	const mix_log_api_type obj##_api = {                                                    \
		obj##_init,                                                                         \
		obj##_save,                                                                         \
		obj##_read,                                                                         \
		obj##_clr,                                                                          \
		obj##_flag_set,                                                                     \
		obj##_site_move,                                                                    \
		obj##_is_site_valid,                                                                \
		obj##_modify,                                                                       \
		obj##_blk_iter,                                                                     \
		obj##_site_iter,                                                                    \
		obj##_time_iter,                                                                    \
		obj##_m_site_iter,                                                                  \
		obj##_m_time_iter,                                                                  \
		obj##_time_search}

#define mix_log_api_ref(obj) extern const mix_log_api_type obj##_api
#define mix_log_api_name(obj) &obj##_api

#ifdef __cplusplus
}
#endif

#endif 
